#!/bin/bash  
#这段脚本是一个基于 Bash 编写的服务器巡检脚本。它可以帮助运维人员自动检查多台服务器的状态，包括主机存活状态、磁盘使用率、内存使用率、CPU 使用率、网络流量以及关键业务服务的状态。

# 定义邮箱和告警阈值
ALERT_EMAIL="你的邮箱"  # 设置告警邮件的接收邮箱地址
DISK_THRESHOLD=80       # 设置磁盘使用率超过 80% 时触发告警
MEM_THRESHOLD=80        # 设置内存使用率超过 80% 时触发告警
CPU_THRESHOLD=80        # 设置 CPU 使用率超过 80% 时触发告警

# 读取主机清单
HOSTS=$(cat hostip.txt)  # 从文件 hostip.txt 读取所有要巡检的主机 IP 地址

# 获取主机名的函数
get_hostname() {
    ssh -o ConnectTimeout=5 $1 "hostname" 2>/dev/null  # 使用 SSH 连接主机，获取主机名，超时设置为 5 秒，错误输出重定向到 /dev/null
}

# 报警函数（用于单条信息发送）
send_alert() {
    local message=$1  # 第一个参数作为报警信息
    local subject=$2   # 第二个参数作为邮件主题
    if [ "$send_email" = "y" ]; then  # 如果用户选择开启邮件报警功能
        echo "$message" | mail -s "$subject" "$ALERT_EMAIL"  # 发送邮件，-s 指定邮件主题
    fi
    echo "$message"  # 输出报警信息到终端
}

# 主机存活检查函数
check_host_alive() {
    ping -c 2 -W 1 $1 &>/dev/null  # 使用 ping 命令检查主机是否可达，发送 2 次 ICMP 请求，等待 1 秒
    if [ $? -ne 0 ]; then  # 如果 ping 命令失败
        report_message+="ALERT: 主机 $hostname ($1) 不可达\n"  # 添加主机不可达的报警信息
    else
        report_message+="$hostname ($1) 存活\n"  # 如果 ping 成功，报告主机存活
    fi
}

# 磁盘使用率检查函数
check_disk_usage() {
    ssh $1 "df -hT | awk -v threshold=$DISK_THRESHOLD 'NR>1 {if(\$6+0 > threshold) print \$7, \$6}'" 2>/dev/null | while read filesystem usage; do  # 使用 df 命令检查磁盘使用情况，超出阈值时打印分区名称和使用率
        if [ -n "$filesystem" ]; then  # 如果磁盘分区信息不为空
            report_message+="ALERT: 主机 $hostname ($1) 磁盘 $filesystem 使用率为 $usage%\n"  # 添加磁盘使用率超标的报警信息
        else
            report_message+="$hostname ($1) 磁盘使用率正常\n"  # 磁盘使用率正常
        fi
    done
}

# 内存使用率检查函数
check_mem_usage() {
    usage=$(ssh $1 "free | awk '/Mem:/ {printf(\"%.0f\", (\$3/\$2)*100)}'" 2>/dev/null)  # 使用 free 命令计算内存使用率，输出为百分比
    if [ $usage -gt $MEM_THRESHOLD ]; then  # 如果内存使用率超过阈值
        report_message+="ALERT: 主机 $hostname ($1) 内存使用率为 $usage%\n"  # 添加内存使用率超标的报警信息
    else
        report_message+="$hostname ($1) 内存使用率为 $usage%\n"  # 正常输出内存使用率
    fi
}

# CPU使用率检查函数
check_cpu_usage() {
    usage=$(ssh $1 "top -bn1 | grep 'Cpu(s)' | awk '{print 100 - \$8}'" 2>/dev/null)  # 使用 top 命令获取 CPU 使用率，输出为百分比
    if (( $(echo "$usage > $CPU_THRESHOLD" | bc -l) )); then  # 使用 bc 命令进行浮动点比较，判断是否超过阈值
        report_message+="ALERT: 主机 $hostname ($1) CPU使用率为 $usage%\n"  # 添加 CPU 使用率超标的报警信息
    else
        report_message+="$hostname ($1) CPU使用率为 $usage%\n"  # 正常输出 CPU 使用率
    fi
}

# 网络流量检查函数
check_network_traffic() {
    ssh $1 "ifconfig eth0 | awk '/RX packets/ {print \"流入: \" \$5} /TX packets/ {print \"流出: \" \$5}'" 2>/dev/null | while read line; do  # 使用 ifconfig 命令检查 eth0 网络接口的流入流量（RX）和流出流量（TX）
        report_message+="$hostname ($1) 网络 $line\n"  # 输出网络流量信息
    done
}

# 业务服务检查函数
check_services() {
    for service in mysql nginx; do  # 检查 mysql 和 nginx 服务
        ssh $1 "systemctl is-active --quiet $service" 2>/dev/null  # 使用 systemctl 命令检查服务状态，如果服务未运行则返回非零状态
        if [ $? -ne 0 ]; then  # 如果服务未运行
            report_message+="ALERT: 主机 $hostname ($1) 的 $service 服务停止\n"  # 添加服务停止的报警信息
        else
            report_message+="$hostname ($1) 的 $service 服务正常\n"  # 服务正常
        fi
    done
}

# 主程序开始

# 用户确认是否发送邮件报警
read -p "是否开启邮件报警功能？(y/n): " send_email  # 提示用户是否开启邮件报警功能

# 开始巡检
echo "=== 开始主机巡检 ==="  # 输出开始巡检的提示

for HOST in $HOSTS; do  # 遍历所有主机
    hostname=$(get_hostname $HOST)  # 获取主机名
    if [ -z "$hostname" ]; then  # 如果无法获取主机名
        hostname="未知主机名"  # 设置为默认的主机名
        echo "无法获取 $HOST 的主机名，跳过巡检。"  # 输出错误信息
        continue  # 跳过当前主机，进入下一个主机的检查
    fi

    # 初始化每台主机的汇总信息
    report_message="==== 巡检主机: $hostname ($HOST) ====\n"  # 为当前主机创建一个报告信息头

    # 调用各个检查函数
    check_host_alive $HOST  # 检查主机存活情况
    check_disk_usage $HOST  # 检查磁盘使用情况
    check_mem_usage $HOST   # 检查内存使用情况
    check_cpu_usage $HOST   # 检查 CPU 使用情况
    check_network_traffic $HOST  # 检查网络流量
    check_services $HOST    # 检查业务服务状态

    # 发送汇总信息
    if [ "$send_email" = "y" ]; then  # 如果用户选择发送邮件
        echo -e "$report_message" | mail -s "主机巡检报告: $hostname ($HOST)" "$ALERT_EMAIL"  # 发送巡检报告邮件
    fi

    # 输出汇总信息到终端
    echo -e "$report_message"  # 输出巡检报告到终端

    echo "==== $hostname ($HOST) 巡检完成 ===="  # 输出当前主机巡检完成的提示
done

echo -e "\n=== 主机巡检结束 ==="  # 输出巡检结束的提示
